package com.yuyue.springFramework.note03;

import com.yuyue.springFramework.note03.cglib.CostCglib;
import com.yuyue.springFramework.note03.cglib.CostCglib2;
import com.yuyue.springFramework.note03.primitive.PrimitiveProxy;
import com.yuyue.springFramework.note03.proxy.CostInvocationHandler;
import com.yuyue.springFramework.note03.proxy.CostInvocationHandler2;
import com.yuyue.springFramework.note03.service.IService;
import com.yuyue.springFramework.note03.service.ServiceA;
import org.junit.Test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 《Spring-3 代理(JDK动态代理和CGLIB代理)》文章代码
 *  文章地址：https://mp.weixin.qq.com/s/V-nZPxzvcfsV3jF50XKOZQ
 */
public class Note3Test {
    @Test
    //手动实现代理
    public void fun1() {
        IService iservice = new ServiceA();
        PrimitiveProxy primitiveProxy = new PrimitiveProxy(iservice);

        primitiveProxy.fun1();
        primitiveProxy.fun2();
        primitiveProxy.fun3();
    }

    @Test
    //jdk动态代理未优化
    public void fun2() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //创建被代理的类对象
        final IService iService1 = new ServiceA();
        //创建执行类，处理代理内容
        InvocationHandler invocationHandler = new InvocationHandler() {
            //重写执行方法，将被代理对象的方法作为参数传入，处理被代理对象方法执行前后的逻辑
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("代理前执行");

                //执行被代理对象方法，并获取其返回值
                Object object = method.invoke(iService1, args);

                System.out.println("代理后执行");
                return object;
            }
        };

        //创建代理类Class
        Class<IService> proxyClass = (Class<IService>) Proxy.getProxyClass(IService.class.getClassLoader(), IService.class);

        //获取代理对象
        IService iService = proxyClass.getConstructor(InvocationHandler.class).newInstance(invocationHandler);

        iService.fun1();
        iService.fun2();
        iService.fun3();
    }

    @Test
    //jdk动态代理，方式一
    public void fun3() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        IService iService = CostInvocationHandler.createProxy(new ServiceA(), IService.class);

        iService.fun1();
        iService.fun2();
        iService.fun3();
    }

    @Test
    //jdk动态代理，方式二
    public void fun4() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        IService iService = CostInvocationHandler2.createProxy(new ServiceA(), IService.class);

        iService.fun1();
        iService.fun2();
        iService.fun3();
    }

    @Test
    //jdk动态代理，是否执行拦截所有方法
    public void fun5() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        IService iService = CostInvocationHandler2.createProxy(new ServiceA(), IService.class);

        iService.fun1();
    }

    @Test
    //Cglib实现
    public void fun6(){
        CostCglib costCglib = new CostCglib();
        IService iService = costCglib.createProxy(ServiceA.class);

        iService.fun1();
        iService.fun2();
        iService.fun3();
    }

    @Test
    //Cglib代理优化
    public void fun7(){
        IService iService = CostCglib2.createProxy(new ServiceA());

        iService.fun1();
        iService.fun2();
        iService.fun3();
    }
}
